package com.xygz.orm.enums;


/**
 * 支持的数据库类型
 *
 * @author xiyuan-lgz 2023-08-13 @version v1.0.0 新建与整理
 */
@SuppressWarnings("SpellCheckingInspection")
public enum DbType {
    
    /**
     * SQLITE
     */
    SQLITE("SQLite", "SQLite数据库") {},
    
    /**
     * MYSQL
     */
    MySQL("MySQL", "MySQL数据库", "mysql") {
        @Override
        public String wrapKeyword(String column) {
            return '`' == column.charAt(0) ? column : '`' + column + '`';
        }
    },
    
    /**
     * SQLServer数据库, TODO 需要注意版本之间的 语法
     */
    SQL_SERVER("MSSQL", "SQLServer数据库", "mssql", "SQL Server") {
        @Override
        public String wrapKeyword(String column) {
            return '[' == column.charAt(0) ? column : '[' + column + ']';
        }
    },
    
    /**
     * ORACLE, TODO 需要注意版本之间 的语法 12c+ new pagination
     */
    ORACLE("Oracle", "Oracle数据库") {},
    
    /**
     * POSTGRE
     */
    POSTGRE_SQL("PostgreSQL", "Postgre SQL数据库", "Postgre SQL", "pgsql") {},
    /**
     * 武汉达梦,作为老牌自研数据库，对 SQL 92 和 SQL 99 的核心特性有很好的支持，并且兼容 Oracle 语法。
     */
    DM("dm", "达梦数据库", "dmsql") {},
    /**
     * Kingbase
     */
    KINGBASE_ES("kingbasees", "人大金仓数据库", "KingbaseES"),
    /**
     *
     * 蚂蚁集团 (OceanBase),完全自主研发，高度兼容 SQL 92 标准，同时在分布式和高可用方面有大量扩展，兼容 MySQL/Oracle 模式。
     */
    OceanBase("OceanBase", "OceanBase", "dmsql") {},
    /**
     * PingCAP (TiDB)
     * 由于兼容 MySQL 5.7 协议，而 MySQL 支持 SQL 92，因此 TiDB 也完全支持。它是通过兼容 MySQL 来间接实现的。
     */
    TiDB("TiDB", "TiDB") {},
    /**
     * 华为(OpenGauss),源自 PostgreSQL，而 PostgreSQL 以高度支持 SQL 标准著称。OpenGauss 继承了这一特性，并对 SQL 92/99/2003 有很好的支持。
     */
    OpenGauss("OpenGauss", "OpenGauss") {},
    /**
     * 华为(GaussDB),华为云上的商用数据库，基于 OpenGauss 或自研内核，对 SQL 标准支持完善。
     */
    GaussDB("GaussDB", "GaussDB") {},
    
    /**
     * 腾讯，（TDSQL）
     * <p>
     * 基于 MySQL 和 PostgreSQL 内核发展而来，天然支持 SQL 92 标准，并在此基础上提供了分布式扩展。
     */
    TDSQL("TDSQL", "TDSQL") {},
    
    /**
     * 阿里云（PolarDB）
     * <p>
     * 作为云原生数据库，其 PostgreSQL/MySQL 兼容版完全继承了上游对 SQL 92 的支持。
     */
    PolarDB("PolarDB", "PolarDB") {},
    
    
    /**
     * DB2
     */
    DB2("db2", "DB2数据库") {},
    
    
    /**
     * MARIADB
     */
    MARIADB("MariaDB", "MariaDB数据库") {},
    
    /**
     * H2
     */
    H2("H2", "H2数据库") {},
    
    /**
     * HSQL
     */
    HSQL("HSQL", "HSQL数据库") {},
    
    /**
     * xugu
     */
    XU_GU("xugu", "虚谷数据库"),
    
    
    GBASE("gbase", "南大通用(华库)数据库"),
    /**
     * GBase-8s
     */
    GBASE_8S("gbase-8s", "南大通用数据库 GBase 8s") {},
    /**
     * Sybase
     */
    SYBASE("sybase", "Sybase ASE 数据库") {},
    /**
     * UNKONWN DB
     */
    OTHER("other", "其他数据库");
    /**
     * 数据库名称
     */
    private final String type;
    /**
     * 描述
     */
    private final String desc;
    
    /**
     * 别名扩展
     */
    private final String[] exts;
    
    DbType(String db, String desc, String... exts) {
        this.type = db;
        this.desc = desc;
        this.exts = exts;
    }
    
    @Override
    public String toString() {
        return this.getType();
    }
    
    public String getType() {
        return type;
    }
    
    public String getDesc() {
        return this.desc;
    }
    
    /**
     * 关键字包裹（数据库字段列 包含管关键字 ）sql 语句 select tab.name,tab.desc from tab
     * <p>
     * 关键字为，tab,name, desc 则包裹后如下
     * <p>
     * MySQL:  select `tab`.`name`，`tab`.`desc` from `tab`
     * <p>
     * SQL Server:  select [tab].[name]，[tab].[desc] from [tab]
     *
     * @param key 关键字
     */
    public String wrapKeyword(String key) {return key;}
    
    /**
     * 获取数据库类型
     *
     * @param dbType 数据库类型字符串
     */
    public static DbType getDbType(String dbType) {
        if (dbType == null) {
            return null;
        }
        for (DbType type : DbType.values()) {
            if (type.type.equalsIgnoreCase(dbType)) {
                return type;
            }
            
            dbType = dbType.toLowerCase();
            for (int i = 0; i < type.exts.length; i++) {
                String tp = type.exts[i];
                if (tp.equalsIgnoreCase(dbType) || dbType.contains(tp) || dbType.contains(tp.toLowerCase())) {
                    return type;
                }
            }
        }
        
        return OTHER;
    }
}
